// SPDX-License-Identifier: Mulan PSL v2
/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * This software is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

//!
//! This module implements efficient binary serialization of Request objects
//! using the bytewise mechanism, providing better performance and smaller storage overhead.

use super::RecorderError;
use crate::ipc::bytewise::{BytewiseBuffer, BytewiseReadOwned, BytewiseWrite, BytewiseWriter};

/// Convenience function: Serialize any object that implements the BytewiseWrite trait
pub fn serialize_record<T: BytewiseWrite>(obj: &T) -> Result<Vec<u8>, RecorderError> {
    // Directly use the original bytewise serialization method, keeping it simple and efficient
    let mut buffer = vec![0u8; 1024 * 1024]; // 1MB buffer
    let mut writer = BytewiseBuffer::new(&mut buffer);

    obj.write_to(&mut writer).map_err(|e| {
        RecorderError::Serialization(format!("Object serialization failed: {:?}", e))
    })?;

    let written_size = writer.written_bytes();
    buffer.truncate(written_size);

    Ok(buffer)
}

/// Convenience function: Deserialize any object that implements the BytewiseReadOwned trait
pub fn deserialize_record<T>(data: &mut [u8]) -> Result<T, RecorderError>
where
    T: BytewiseReadOwned,
{
    let mut reader = BytewiseBuffer::new(data);

    T::read_from_mut(&mut reader).map_err(|e| {
        RecorderError::Deserialization(format!("Object deserialization failed: {:?}", e))
    })
}

/// Convenience function: Serialize a single Request (backward compatible)
pub fn serialize_request(request: &impl BytewiseWrite) -> Result<Vec<u8>, RecorderError> {
    serialize_record(request)
}

/// Convenience function: Deserialize a single Request (backward compatible)
pub fn deserialize_request<T: BytewiseReadOwned>(data: &mut [u8]) -> Result<T, RecorderError> {
    deserialize_record(data)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::ipc::message::{Argument, ArgumentFlag, Request};

    #[test]
    fn test_request_serialization() {
        // Create test Request
        let request = Request::with_args(
            0x12345678,
            vec![
                Argument::from_value(42u32, ArgumentFlag::ARG_IN),
                Argument::from_value(3.14f64, ArgumentFlag::ARG_OUT),
                Argument::from_value("test".as_bytes(), ArgumentFlag::ARG_VIRT),
            ],
        );

        // Serialize
        let mut serialized = serialize_request(&request).unwrap();
        assert!(!serialized.is_empty());

        // Deserialize
        let deserialized: Request = deserialize_request(&mut serialized).unwrap();

        // Verify
        assert_eq!(deserialized.method_id(), request.method_id());
        assert_eq!(deserialized.argc(), request.argc());
        assert_eq!(deserialized.request_id(), request.request_id());
    }

    #[test]
    fn test_empty_request_serialization() {
        let request = Request::empty(0xABCDEF);
        let mut serialized = serialize_request(&request).unwrap();
        let deserialized: Request = deserialize_request(&mut serialized).unwrap();

        // Verify
        assert_eq!(deserialized.method_id(), request.method_id());
        assert_eq!(deserialized.argc(), request.argc());
        assert_eq!(deserialized.request_id(), request.request_id());
    }

    #[test]
    fn test_batch_serialization() {
        let requests = vec![
            Request::empty(1),
            Request::with_arg(2, Argument::from_value(100i32, ArgumentFlag::ARG_IN)),
            Request::with_args(
                3,
                vec![
                    Argument::from_value(1.5f32, ArgumentFlag::ARG_IN),
                    Argument::from_value(2.5f64, ArgumentFlag::ARG_OUT),
                ],
            ),
        ];

        // Serialize each request
        for request in &requests {
            let mut serialized = serialize_request(request).unwrap();
            let deserialized: Request = deserialize_request(&mut serialized).unwrap();
            assert_eq!(deserialized.method_id(), request.method_id());
            assert_eq!(deserialized.argc(), request.argc());
            assert_eq!(deserialized.request_id(), request.request_id());
        }
    }

    #[test]
    fn test_global_functions() {
        let request = Request::with_arg(
            0x999,
            Argument::from_slice("global_test".as_bytes(), ArgumentFlag::ARG_IN),
        );

        let mut serialized = serialize_request(&request).unwrap();
        let deserialized: Request = deserialize_request(&mut serialized).unwrap();

        // Verify
        assert_eq!(deserialized.method_id(), request.method_id());
        assert_eq!(deserialized.argc(), request.argc());
        assert_eq!(deserialized.request_id(), request.request_id());
    }
}
